﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using OpenSource.UPnP;
using System.Xml;
using System.Windows.Markup;
using System.IO;
using System.Reflection;
using System.Threading;
using System.Windows.Threading;
using System.Runtime.CompilerServices;
using System.Collections;


namespace SurfaceServeur
{


    /**
 * \file          MainWindow.xaml.cs
 * \author        sbai
 * \brief         Interaction logic pour MainWindow.xaml.
 *
 * \details       Cette classe définit les méthodes de l'interface graphique utilisateur "MainWindow.xaml".
 */


    public partial class MainWindow : Window
    {
       

        public MainWindow()
        {
            InitializeComponent();
            l = new SurfaceServeur.UPnPSurfaceServeur();
        }
        
        SurfaceServeur.UPnPSurfaceServeur l;
        SurfaceServeur.ClientSurfaceServeur2 client2;

        Window x = null;

       
        static ArrayList _zonesException = new ArrayList();

        /**
        * \brief      Contient les exceptions détectées lors de la génération de l'interface graphique.
        * \details    ArrayList qui contients le nom du composant qui a déclenché l'exception, son type, le nom de l'évènement, la méthode à invoquer côté client.
     */
        static public ArrayList ZonesException
        { get { return _zonesException; } set { _zonesException = value; } }



        /**
    * \chargement_UI       La fonction chargement_UI() est la fonction principale, elle permet de générer l'interface graphique afin de 
         * recuperer les exceptions trouvées dans un ArrayList "_zonesException"
    */
        public void chargement_UI()
        {
            Console.WriteLine("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
            //voir quelles sont les classes liées à la classe Button
            Button button=new Button();
            Type oType = button.GetType();
            MethodInfo[] ListMethods = oType.GetMethods();
           /* foreach (MethodInfo mi in ListMethods)
            {
                Console.WriteLine(mi);
            }
            */
            Console.WriteLine("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");

           //SurfaceServeur.UPnPSurfaceServeur.Zones[0] contient le fichier de description sans le namespace

           string chaine=SurfaceServeur.UPnPSurfaceServeur.Zones[0].ToString();

           Console.WriteLine("le contenu du fichier de description que le serveur a reçu est: \n" +chaine );
            


            //démarrer un CP

           client2 = new SurfaceServeur.ClientSurfaceServeur2(this);
           client2.startUPnP();

           int n = 0;


           while (n != 1)
           {
               try
               {

                   XmlReader reader2 = XmlReader.Create(new StringReader(chaine));
                   x = new Window();
                   x = (Window)XamlReader.Load(reader2);
                   Console.Write("le load est faittttttttttttt");
                   n++;
                   Console.WriteLine(n);

               }

               catch (XamlParseException ex)
               {
                   Console.WriteLine(" XamlParseException:");
                   Console.WriteLine("Il y a une erreur, plus d'informations ci-dessous :");
                   Console.WriteLine();
                   Console.WriteLine("\n Type de l'exception : " + ex.GetType());
                   Console.WriteLine();
                   Console.WriteLine("Message d'erreur : " + ex.Message);
                   Console.WriteLine();

                   string s = ex.Message;
                   //s ='Échec de la création d'un 'Click' à partir du texte 'button1_Click'.
                   //' numéro de ligne '1' et position de ligne '365'.(par exemple)

                   int first = s.IndexOf("'") + 1;

                   int last = s.IndexOf(".");

                   //s contient la chaîne qui donne information sur l'événement et le nom de la méthode

                   s = s.Substring(first, last - first);

                   //s=Échec de la création d'un 'Click' à partir du texte 'button1_Click'
                   Console.WriteLine("la valeur de s est: \n " + s);

                   //splitted1 est un arraylist à 3 cases qui contient le nom de l'événement/ le nom de la méthode

                   string[] splitted = s.Split('\'');

                   string[] splitted1 = new string[3];

                   Console.WriteLine("détection de l'event");
                   splitted1[0] = splitted[2];
                   Console.WriteLine("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");
                   Console.WriteLine(splitted[2]);
                   //splitted1[0]=Click== event

                   Console.WriteLine("détection du nom de la methode");

                   splitted1[1] = splitted[4];
                   Console.WriteLine(splitted[4]);

                   //splitted1[0]=button1_Click== nom de la méthode
                   Console.WriteLine("%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%");

                   // _zones3 contient pr le moment(Click, button1_Click )=(event, nom de la méthode)


                   //Maintenant je veux récupérer le nom du composant et son type
                   string[] splitted2 = chaine.Split('<');

                   for (int i = 1; i < splitted2.Length; i++)
                   {
                       //splitted2 contient le fichier de description
                       splitted2[i] = "<" + splitted2[i];

                       Console.WriteLine(splitted2[i]);
                   }



                   Console.WriteLine("*****************************************************************");

                   for (int i = 1; i < splitted2.Length; i++)
                   {


                       if (splitted2[i].Contains(splitted[2]) && splitted2[i].Contains(splitted[4]))
                       {
                           Console.WriteLine(splitted2[i]);
                         Console.WriteLine("j'ai trouvé une valeur");

                           //nom contient le nom de la l'objet associé à l'événement et la méthode à appeler


                         int t1 = splitted2[i].IndexOf("Name=\"");
                         int t2 = splitted2[i].IndexOf("\"");
                           string nom = splitted2[i].Substring(splitted2[i].IndexOf("Name=\""), splitted2[i].IndexOf("\""));

                           Console.WriteLine("le nom est :  " + nom);


                           int first3 = nom.IndexOf("\"") + 1;
                           Console.WriteLine("le first est :  " + first3);

                           int last3 = nom.LastIndexOf("\"");
                           Console.WriteLine("le last est :  " + last3);
                           //maintenant splitted1 contient le nom de l'événement/ le nom de la méthode/ le nom de l'objet

                           //Console.WriteLine("détection du nom de composantttttttttttttttttttt");
                           string name = nom.Substring(first3, last3-first3);
                           Console.WriteLine("le name est :" + name);

                           //maintenant splitted1 contient le nom de l'événement/ le nom de la méthode/ le nom de l'objet/ le type de composant(Button, checkbox...)

                           //Console.WriteLine("###########################################################");

                           //Console.WriteLine("détection du type de composantttttttttttttttttttt");

                           string Typecomposant = splitted2[i].Substring(splitted2[i].IndexOf("<") + 1, splitted2[i].IndexOf(" ")-1);

                           //Console.WriteLine(Typecomposant);
                           //Typecomposant = Typecomposant.Trim();
                           _zonesException.Add(Typecomposant);
                           _zonesException.Add(name);
                           _zonesException.Add(splitted[2]);
                           _zonesException.Add(splitted[4]);

                           //Console.WriteLine("###########################################################");



                          
                           string b = splitted1[0] + "=\"" + splitted1[1] + "\"";
                           //exemple de valeur de b= Click="button1_Click"

                           //Console.WriteLine("b est de valeuuurrrrrrrrr : " +b);

                           chaine = chaine.Replace(b, "");
                           //Console.WriteLine("la deuxième chaine est : \n" + chaine);

                       }

                   }

                   
                   for (int k = 0; k < _zonesException.Count; k++)
                   {

                       Console.WriteLine(_zonesException[k]);
                                                                  
                   }

                  
                   Console.WriteLine("*****************************************************************");


               }
               catch (Exception ex)
               {
                   Console.WriteLine("Exception:");
                   Console.WriteLine("Il y a une erreur, plus d'informations ci-dessous :");

                   Console.WriteLine();
                   Console.WriteLine("Message d'erreur : " + ex.Message);

                   Console.WriteLine();
                   Console.WriteLine("Type de l'exception : " + ex.GetType());
               }
           }

           Grid grid1 = (Grid)x.FindName("Grid");
           int q = 0;
           EventInfo[] list;
           
                        
           Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
           
            int tt = _zonesException.Count;

           Console.WriteLine("tt esttttttttttttttttttttttttttttttt  " +tt);
            for (int c = 1; c < _zonesException.Count; c++)
                  
                  {
                      string nomComposant = (string)_zonesException[c];

                      Console.WriteLine("le nom du composant estttttttttttt  "+nomComposant);
                      
               
                   var myT = x.FindName(nomComposant);

                   if (myT != null) { 
                       
                       
                   Console.WriteLine("le composant "+nomComposant+ " existe  <<<<<<<<<<<<<<<<<<<<<<<<<<<<");


                   list = myT.GetType().GetEvents();

                   Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");

                   for (int f = 0; f < list.Length; f++)
                   {
                       string nomevent=list[f].Name;
                       string nomeventtab = (string)_zonesException[c + 1];

                       if (nomevent == nomeventtab)
                       {
                           Console.WriteLine(nomevent);
                           Console.WriteLine("GOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOOO");
                           //Ajout de l'évènement au composant (par exemple event= Click)
                           var evt = myT.GetType().GetEvent(nomevent);
                           RoutedEventHandler myCode = delegate { methodeEvent(myT, null); };
                           evt.AddEventHandler(myT, myCode);
                           Console.WriteLine("Ajout de l'évènement " + nomeventtab + " au composant "+nomComposant);

                       }

                   }

                   Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");
                
                   }


                   else { Console.WriteLine("le composant " + nomComposant + " n'existe pas  >>>>>>>>>>>>>>>>>>>"); }

                   c = c + 3;                  
        }
           

           Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");         

           x.ShowDialog();
                     
        }


        /**
* \methodeEvent            pour récupérer la liste des événements liés aux composants de l'interface graphique générée
* \param    sender         sender est le nom du composant qui a déclenché l'évènement.
* \param    e              e est l'évènement déclenché par le sender.
*/
        private void methodeEvent(object sender, EventArgs e)
        {
            Console.WriteLine("Appel de la méthode 'methodeEvent' ");
            Console.WriteLine("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");

          /*  Image image = (Image)x.FindName("image1");

            if (image != null)
            {
                
            Console.WriteLine("il y a une imaaaaaaaaaaageeeeeeeeeeeee");
            Binding tmpBinding = new Binding();
            string d = "http://bdzoom.com/wp-content/uploads/2011/11/ib815image-une-eruption-solaire-prise-avec-instrument-eit-installe-bord-satellite-soho-esa-nasa.jpg";
            tmpBinding.Source = new Uri(@d, UriKind.Absolute);

            image.SetBinding(Image.SourceProperty, tmpBinding);

            }
            */
           
            string nom = (sender as Control).Name;

            Console.WriteLine("le senderrrrrrrrrrrrrrrrrrrrr  esttt  " + nom);

           
            for (int h = 1; h < _zonesException.Count; h++)
            {
                string composant=_zonesException[h].ToString();
                
                //name==nom du button qui a déclencher l'événement

                string name = _zonesException[h].ToString();
                
                if(nom==name){

                    Console.WriteLine("!!!!!!!!!!!!!!!!!!!Test!!!!!!!!!!!!!!!!!!!!");
                    Console.WriteLine("j'ai trouvé le sender "+ name);
                    Console.WriteLine("!!!!!!!!!!!!!!!!!!!Fin du Test!!!!!!!!!!!!!!!!!!!!");

                    string meth = _zonesException[h+2].ToString();

                    invockMeth(meth, name);
                    
                }
                h = h + 3;
                
            }
            
        }





        /**
* \invockMeth            pour récupérer la liste des événements liés aux composants de l'interface graphique générée
* \param    meth         meth est le nom de la méthode à invoquer.
* \param    name         name est le nom du composant lié à cette méthode.
*/
        public void invockMeth(string meth, string name)
        {
            Console.WriteLine("methode invoquee " +meth +" par "+ name);

            
            client2.Search(meth);
        }

        /**
        * \changeresultat          méthode intermédiaire pour invoquer la méthode qui va récupérer le résultat final.
         * dans cette méthode j'ai utilisé le dispatcher qui va exécuter du code sur l'interface utilisateur (UI)
         * à partir d'un thread non-UI (à partir du thread UPnP).
        * \param    component    le nom d'un composant de l'interface graphique générée.
        * \param    propriete    la propriété du composant.
        * \param    valeur       la valeur de la propriété du composant à mettre à jour.
        */
        public void changeresultat(string component, string propriete, string valeur) {

            Console.WriteLine("invocation de la méthode 'changeresultat' ");

            Dispatcher.BeginInvoke(DispatcherPriority.Normal, (Action)delegate()
            {

                Console.WriteLine("Invoker la méthode 'recupereResultat'");
                recupereResultat(component, propriete, valeur);
            });

        
        }

        /**
        * \recupereResultat          méthode intermédiaire pour récupérer le résultat final.
        * \param    component    le nom d'un composant de l'interface graphique générée.
        * \param    propriete    la propriété du composant.
        * \param    valeur       la valeur de la propriété du composant à mettre à jour.
        */
        public void recupereResultat(string component, string propriete, string valeur)
        {

            Console.WriteLine("la methode recupereResultat est appelée ???????????????????????????????");
            Console.WriteLine("la propriétééééééééééé esttt " + propriete + " la propriétééééééééééé esttt");

             
              var element = x.FindName(component);
              

                  if (element.GetType() == typeof(Image)) {

                      Console.WriteLine("Ouiiiiiiiiii c'est une imaaaaaaaaaaaaaaageeeeeeeeeeeeeeeeee");

                      Image im11 = (Image)element;


                      Binding tmpBinding = new Binding();
                      string d = valeur;
                      tmpBinding.Source = new Uri(@d, UriKind.Absolute);

                      im11.SetBinding(Image.SourceProperty, tmpBinding);
                  }
                 
        
              PropertyInfo[] list5;

              

                if (propriete.Contains(" "))
                {
              propriete=propriete.Trim();
                }
                if (element != null)
                {

                    Console.WriteLine("trueeeeeeeeee");
                    list5 = element.GetType().GetProperties();

                    Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");

                    for (int f = 0; f < list5.Length; f++)
                    {
                        string propertyy = list5[f].Name;

                        if (propertyy == propriete)
                        {
                            Console.WriteLine(propertyy);

                            var prop = element.GetType().GetProperty(propertyy).GetValue(element, null);

                            Console.WriteLine("PRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR " + prop);

                            try
                            {
                                element.GetType().GetProperty(propertyy).SetValue(element, valeur, null);
                            }


                            catch (ArgumentException ex)
                            {
                                Console.WriteLine("Exception:");
                                Console.WriteLine("Il y a une erreur, plus d'informations ci-dessous :");

                                Console.WriteLine();
                                Console.WriteLine("Message d'erreur : " + ex.Message);

                                Console.WriteLine();
                                Console.WriteLine("Type de l'exception : " + ex.GetType());
                              try
                                   {
                                       int val = int.Parse(valeur);

                                       Console.WriteLine("valllllllllllllllllllllllll   :   " + val);
                                       element.GetType().GetProperty(propertyy).SetValue(element, val, null);
                                   }
                                   catch (ArgumentException ex1) {
                                       Console.WriteLine("Exception:");
                                       Console.WriteLine("Il y a une erreur, plus d'informations ci-dessous :");

                                       Console.WriteLine();
                                       Console.WriteLine("Message d'erreur : " + ex1.Message);

                                       Console.WriteLine();
                                       Console.WriteLine("Type de l'exception : " + ex1.GetType());


                                
                                   }

                            }
                            catch (Exception ex) {

                                Console.WriteLine("Exception:");
                                Console.WriteLine("Il y a une erreur, plus d'informations ci-dessous :");

                                Console.WriteLine();
                                Console.WriteLine("Message d'erreur : " + ex.Message);

                                Console.WriteLine();
                                Console.WriteLine("Type de l'exception : " + ex.GetType());
                            }




                        }

                    }

                    Console.WriteLine("&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&");



                }

                else { Console.WriteLine("falseeeeeeeeeeeeeeeeee"); }


            
        
        }



        /**
        * \ButtonCloseClicked      méthode pour arrêter le device UPnP.
        * \param    sender         Le déclencheur de l'évènement.
        * \param    e              l'évènement icic est un Click sur le button.
        
        */
        private void ButtonCloseClicked(object sender, RoutedEventArgs e)
        {
            l.stopUPnP();

        }


        /**
        * \button3_Click           méthode pour démarrer le device UPnP.
        * \param    sender         Le déclencheur de l'évènement.
        * \param    e              l'évènement ici est un Click sur le button.
        
        */
        private void button3_Click(object sender, RoutedEventArgs e)
        {         
            l.startUPnP();
           RefreshMessage("le Device 'UPnPSurfaceServeur' est connecté");
          
        }


        /**
       * \button1_Click           méthode pour fermer l'interface MainWindow.
       * \param    sender         Le déclencheur de l'évènement.
       * \param    e              l'évènement icic est un Click sur le button.
        
       */
        private void button1_Click(object sender, RoutedEventArgs e)
        {
            l.stopUPnP();
            this.Close();  
        }


        /**
       * \button4_Click           méthode pour appeler la méthode qui va générer l'interface graphique.
       * \param    sender         Le déclencheur de l'évènement.
       * \param    e              l'évènement icic est un Click sur le button.
        
       */
        private void button4_Click(object sender, RoutedEventArgs e)
        {
            RefreshMessage("le Device 'UPnPSurfaceServeur'est entrain de créer l'interface graphique demandée");
            chargement_UI();
        }


        private void RefreshMessage(string message)
        {
            Mes.Text = message;
            Mes.Refresh();
        }
        
       
        }


    public static class ExtensionMethods
    {
        private static Action EmptyDelegate = delegate() { };

        public static void Refresh(this UIElement uiElement)
        {
            uiElement.Dispatcher.Invoke(EmptyDelegate, System.Windows.Threading.DispatcherPriority.Render);
        }
    }
   
}







